/**
 * 控制并发的任务队列管理器
 * 确保同一时间只执行指定数量的任务，一个任务完成后才会执行下一个
 * @class TaskQueue
 * @author ruilin
 */
class TaskQueue {
    #maxTasks;          // 最大并发任务数
    #queue = [];        // 等待执行的任务队列
    #currentCount = 0;  // 当前正在执行的任务数量（核心控制变量）
    #completeCallback;  // 构造函数传入的完成回调
    #startCallback;     // start方法传入的完成回调
    #debug;             // 是否开启调试模式

    /**
     * 初始化任务队列
     * @param {Object} options 配置项
     * @param {number} [options.maxTasks=3] 最大并发任务数，必须大于0
     * @param {Function} [options.complete=()=>{}] 所有任务完成后的回调
     * @param {boolean} [options.debug=false] 是否开启调试日志
     */
    constructor(options = {}) {
        const defaultConfig = {
            maxTasks: 3,
            complete: () => {},
            debug: false
        };

        const config = { ...defaultConfig, ...options };
        this.#validateMaxTasks(config.maxTasks);

        this.#maxTasks = config.maxTasks;
        this.#completeCallback = config.complete;
        this.#debug = config.debug;
        this.#startCallback = null;

        this.#log('任务队列初始化完成', {
            maxTasks: this.#maxTasks,
            debugMode: this.#debug
        });
    }

    /**
     * 校验最大任务数是否合法
     * @param {number} maxTasks 最大任务数
     * @throws {Error} 当最大任务数小于1时抛出错误
     */
    #validateMaxTasks(maxTasks) {
        if (!Number.isInteger(maxTasks) || maxTasks < 1) {
            throw new Error('maxTasks must be a positive integer greater than 0');
        }
    }

    /**
     * 设置最大并发任务数（动态调整）
     * @param {number} maxTasks 新的最大并发任务数
     */
    set maxTasks(maxTasks) {
        this.#validateMaxTasks(maxTasks);
        this.#maxTasks = maxTasks;
        this.#log(`最大并发数调整为: ${maxTasks}`);
        this.#tryExecuteNext(); // 调整后尝试执行更多任务
    }

    /**
     * 获取当前最大并发任务数
     * @returns {number} 最大并发任务数
     */
    get maxTasks() {
        return this.#maxTasks;
    }

    /**
     * 添加任务到队列
     * @param {Function} task 任务函数，必须返回Promise
     * @throws {Error} 当任务不是函数或不返回Promise时抛出错误
     */
    addTask(task) {
        if (typeof task !== 'function') {
            throw new Error('task must be a function');
        }
        
        this.#queue.push(task);
        this.#log(`任务已添加到队列，当前队列长度: ${this.#queue.length}`, {
            当前并发数: this.#currentCount,
            最大并发数: this.#maxTasks
        });
    }

    /**
     * 开始执行队列中的任务
     * @param {Function} [completeCallback] 所有任务执行完成后的回调
     */
    start(completeCallback) {
        this.#startCallback = typeof completeCallback === 'function' 
            ? completeCallback 
            : null;

        if (this.#queue.length === 0) {
            this.#log('任务队列为空，直接触发完成回调');
            this.#triggerComplete();
            return;
        }

        this.#log(`开始执行任务，队列长度: ${this.#queue.length}，最大并发数: ${this.#maxTasks}`);
        this.#tryExecuteNext(); // 开始执行第一批任务
    }

    /**
     * 尝试执行下一个任务（核心并发控制逻辑）
     * 只有当前执行任务数小于最大限制时才会执行新任务
     */
    #tryExecuteNext() {
        // 循环执行，直到达到最大并发数或队列空
        while (this.#currentCount < this.#maxTasks && this.#queue.length > 0) {
            this.#executeNextTask();
        }

        // 检查是否所有任务都已完成
        if (this.#currentCount === 0 && this.#queue.length === 0) {
            this.#log('所有任务执行完成');
            this.#triggerComplete();
        }
    }

    /**
     * 执行队列中的下一个任务
     */
    #executeNextTask() {
        // 取出队列中的第一个任务
        const task = this.#queue.shift();
        if (!task) return;

        // 增加当前执行任务计数
        this.#currentCount++;
        const taskId = Date.now().toString().slice(-4); // 生成简短任务ID用于日志

        this.#log(`开始执行任务 [ID: ${taskId}]`, {
            当前并发数: this.#currentCount,
            剩余队列长度: this.#queue.length
        });

        try {
            task()
                .then(() => {
                    this.#log(`任务执行成功 [ID: ${taskId}]`);
                })
                .catch((error) => {
                    this.#log(`任务执行失败 [ID: ${taskId}]：${error.message}`, 'error');
                })
                .finally(() => {
                    // 任务完成，减少当前执行计数
                    this.#currentCount--;
                    this.#log(`任务完成 [ID: ${taskId}]`, {
                        当前并发数: this.#currentCount,
                        剩余队列长度: this.#queue.length
                    });

                    // 尝试执行下一个任务
                    this.#tryExecuteNext();
                });
        } catch (error) {
            this.#log(`任务执行抛出异常 [ID: ${taskId}]：${error.message}`, 'error');
            this.#currentCount--;
            this.#tryExecuteNext();
        }
    }

    /**
     * 触发完成回调
     */
    #triggerComplete() {
        // 先执行start方法传入的回调
        if (this.#startCallback) {
            try {
                this.#startCallback();
            } catch (error) {
                this.#log(`start回调执行出错: ${error.message}`, 'error');
            }
            this.#startCallback = null;
        }

        // 再执行构造函数传入的回调
        try {
            this.#completeCallback();
        } catch (error) {
            this.#log(`构造函数回调执行出错: ${error.message}`, 'error');
        }
    }

    /**
     * 调试日志输出
     * @param {string} message 日志信息
     * @param {any} [details] 附加详细信息
     * @param {string} [level='log'] 日志级别 (log, warn, error)
     */
    #log(message, details, level = 'log') {
        if (!this.#debug) return;

        const timestamp = new Date().toISOString();
        console[level](`[TaskQueue] [${timestamp}] ${message}`, details || '');
    }
}

export default TaskQueue;
